package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.after.sale.service.IFeignService;
import com.ssy.lingxi.after.sale.utils.FeignLogUtils;
import com.ssy.lingxi.common.constant.order.OrderPurchaseProcessTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderTradeProcessTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.contract.api.feign.ContractExecuteControllerFeign;
import com.ssy.lingxi.contract.api.model.vo.request.ContractExecuteInfoAddVO;
import com.ssy.lingxi.dto.model.constant.ApplyAmountRowBillTypeEnum;
import com.ssy.lingxi.dto.model.constant.SettleAccountsConstant;
import com.ssy.lingxi.dto.request.SettleAccountQueueDTO;
import com.ssy.lingxi.dto.request.SettlementOrderVO;
import com.ssy.lingxi.dto.response.PlatformSettlementAllInPayVO;
import com.ssy.lingxi.feign.PlatformSettlementControllerFeign;
import com.ssy.lingxi.logistics.api.dto.response.LogisticsOrderFeignResponse;
import com.ssy.lingxi.logistics.api.feign.LogisticsOrderControllerFeign;
import com.ssy.lingxi.marketing.api.feign.ActivityGoodsControllerFeign;
import com.ssy.lingxi.marketing.api.model.request.GoodsSalesReq;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberLevelRightCreditControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignAfterSaleCommentVO;
import com.ssy.lingxi.message.api.feign.SystemMessageControllerFeign;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.*;
import com.ssy.lingxi.order.api.model.vo.response.*;
import com.ssy.lingxi.pay.api.dto.request.WeChatRefundRequest;
import com.ssy.lingxi.pay.api.dto.request.aliPay.AliPayRefundRequest;
import com.ssy.lingxi.pay.api.dto.request.assetAccount.BalanceRefundRequest;
import com.ssy.lingxi.pay.api.dto.request.eAccount.EAccountRefundRequest;
import com.ssy.lingxi.pay.api.dto.request.eAccount.StoreRefundRequest;
import com.ssy.lingxi.pay.api.feign.*;
import com.ssy.lingxi.pay.api.model.vo.request.ccb.B2bRefundVO;
import com.ssy.lingxi.pay.api.model.vo.request.ccb.DigitalRefundVO;
import com.ssy.lingxi.pay.api.model.vo.response.allInPay.OrderSplitRefundRespVO;
import com.ssy.lingxi.pay.api.model.vo.response.allInPay.RefundRespVO;
import com.ssy.lingxi.report.api.feign.ReportControllerFeign;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 内部接口服务实现
 */
@Service
public class FeignServiceImpl implements IFeignService {

    private static final Logger logger = LoggerFactory.getLogger(FeignServiceImpl.class);

    @Resource
    private MemberLevelRightCreditControllerFeign memberLevelRightCreditControllerFeign;

    @Resource
    private ReportControllerFeign reportController;

    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private SystemMessageControllerFeign systemMessageControllerFeign;
    @Resource
    private LogisticsOrderControllerFeign logisticsOrderControllerFeign;
    @Resource
    private ActivityGoodsControllerFeign activityGoodsControllerFeign;
    @Resource
    private IWeChatPayFeign weChatPayFeign;
    @Resource
    private IAliPayFeign aliPayFeign;
    @Resource
    private IAllInPayFeign  allInPayFeign;
    @Resource
    private ContractExecuteControllerFeign contractExecuteControllerFeign;
    @Resource
    private PlatformSettlementControllerFeign platformSettlementControllerFeign;
    @Resource
    private ICcbPayFeign ccbPayFeign;
    @Resource
    private IAssetAccountFeign assetAccountFeign;
    @Resource
    private RabbitTemplate rabbitTemplate;
    /**
     * 发送系统通知
     * @author 伍将
     * @date 2020/12/21
     * @param request:请求参数
     **/
    @Async
    @Override
    public void sendSystemMessage(SystemMessageRequest request) {
        try {
            systemMessageControllerFeign.sendSystemMessage(request);
        } catch (Exception e) {
            logger.error("调用消息服务新增系统通知接口失败：{},\n", JSONUtil.toJsonStr(request), e);
        }
    }


    @Override
    public void sendSystemMessage(Long memberId, Long roleId, String messageNotice, String... param) {
        SystemMessageRequest request = new SystemMessageRequest();
        request.setMemberId(memberId);
        request.setRoleId(roleId);
        request.setMessageNotice(messageNotice);
        List<String> params = Stream.of(param).collect(Collectors.toList());
        request.setParams(params);
        sendSystemMessage(request);
    }

    /**
     * 更新订单商品明细
     * @author 伍将
     * @date 2020/12/11
     * @param afterSales: 请求参数
     * @return : 操作结果
     **/
    @Override
    public Wrapper<?> orderProductDetailsUpdate(List<OrderAfterSaleVO> afterSales) {
        Wrapper<?> wrapper =  orderFeignService.updateAfterSaleOrderProduct(afterSales);
        FeignLogUtils.printLog("更新订单商品明细",wrapper,afterSales);
        return wrapper;
    }

    /**
     * 新增会员评价
     * @param commentVO：评价内容
     */
    @Async
    @Override
    public void addMemberEvaluate(MemberFeignAfterSaleCommentVO commentVO) {
        Wrapper<?> wrapper = memberLevelRightCreditControllerFeign.calculateMemberAfterSaleCreditPoint(commentVO);
        if (wrapper != null) {
            if(wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                logger.info("调用会员服务，新增售后评价失败：{}-{}", wrapper.getCode(), wrapper.getMessage());
            }
        }else{
            logger.info("调用会员服务，新增售后评价失败");
        }
    }

    /**
     * 新增系统操作通知
     * @author 伍将
     * @date 2021/1/9
     * @param noticeVO: 请求参数
     **/
    @Async
    @Override
    public void addSysOperateNotice(OperateNoticeVO noticeVO) {
        try {
            reportController.addOperateNotice(noticeVO);
        } catch (Exception e) {
            logger.info("调用报表服务新增操作通知接口失败：{}", e.getMessage());
        }
    }

    @Override
    public Wrapper<List<OrderAfterSaleProductFeignDetailVO>> afterSalesListById(List<OrderProductIdFeignVO> orderProductIds) {
        Wrapper<List<OrderAfterSaleProductFeignDetailVO>> afterSaleOrderProducts = orderFeignService.findAfterSaleOrderProducts(orderProductIds);
        FeignLogUtils.printLog("售后查询订单商品信息",afterSaleOrderProducts,orderProductIds);
        return afterSaleOrderProducts;
    }

    @Override
    public Wrapper<List<OrderAfterSalePaymentFeignDetailVO>> getOrderPayInfo(List<Long> orderIds) {
        OrderIdsFeignVO vo=new OrderIdsFeignVO();
        vo.setOrderIds(orderIds);
        Wrapper<List<OrderAfterSalePaymentFeignDetailVO>> afterSaleOrderProducts = orderFeignService.findAfterSaleOrderPayments(vo);
        FeignLogUtils.printLog("售后查询订单支付信息",afterSaleOrderProducts,orderIds);
        return afterSaleOrderProducts;
    }

    /**
     * 查询采购流程规则
     * @param feignVO: 请求参数
     * @return 采购流程规则
     */
    @Override
    public Wrapper<OrderPurchaseProcessFeignDetailVO> getPurchaseProcess(OrderPurchaseProcessFeignVO feignVO) {
        Wrapper<OrderPurchaseProcessFeignDetailVO> wrapper =  orderFeignService.findBuyerPurchaseProcess(feignVO);
        FeignLogUtils.printLog("查询采购流程规则",wrapper,feignVO);
        return wrapper;
    }


    /**
     * 校验采购流程
     * @param memberId 会员id
     * @param roleId 角色id
     * @param purchaseProcessTypeEnum 采购流程类型枚举
     * @param contractIds 合同id集合
     */
    public void checkPurchaseProcess(Long memberId, Long roleId, OrderPurchaseProcessTypeEnum purchaseProcessTypeEnum, List<Long> contractIds){
        //验证合同采购工作流是否有效
        OrderPurchaseProcessFeignVO requestVO=new OrderPurchaseProcessFeignVO();
        requestVO.setMemberId(memberId);
        requestVO.setRoleId(roleId);
        requestVO.setProcessTypeEnum(purchaseProcessTypeEnum);
        requestVO.setContractIds(contractIds);
        Wrapper<OrderPurchaseProcessFeignDetailVO> purchaseProcess = getPurchaseProcess(requestVO);
        if(purchaseProcess==null){
            throw new BusinessException(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(purchaseProcess.getCode()!=ResponseCode.SUCCESS.getCode()){
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PROCESS_IS_NOT_ALLOW);
        }
    }

    /**
     * 查询交易流程规则
     * @param feignVO: 请求参数
     * @return 交易流程规则
     */
    @Override
    public Wrapper<OrderTradeProcessFeignDetailVO> getTradeProcess(OrderTradeProcessFeignVO feignVO) {
        Wrapper<OrderTradeProcessFeignDetailVO> wrapper =  orderFeignService.findVendorTradeProcess(feignVO);
        FeignLogUtils.printLog("查询交易流程规则",wrapper,feignVO);
        return wrapper;
    }

    /**
     * 校验交易工作流
     * @param memberId 会员id
     * @param roleId 角色id
     * @param tradeProcessTypeEnum 交易流程类型枚举
     * @param skuIds skuIds
     * @param shopId 门店id
     */
    public void checkTradeProcess(Long memberId, Long roleId, OrderTradeProcessTypeEnum tradeProcessTypeEnum, List<Long> skuIds, Long shopId){
        //验证合同采购工作流是否有效
        OrderTradeProcessFeignVO vo=new OrderTradeProcessFeignVO();
        vo.setMemberId(memberId);
        vo.setRoleId(roleId);
        vo.setShopId(shopId);
        vo.setProcessTypeEnum(tradeProcessTypeEnum);
        List<OrderTradeProcessProductFeignVO> feignVOS = skuIds.stream().map(item -> {
            OrderTradeProcessProductFeignVO processProductFeignVO = new OrderTradeProcessProductFeignVO();
            processProductFeignVO.setSkuId(item);
            return processProductFeignVO;
        }).collect(Collectors.toList());
        vo.setProducts(feignVOS);
        Wrapper<OrderTradeProcessFeignDetailVO> purchaseProcess = getTradeProcess(vo);
        if(purchaseProcess==null){
            throw new BusinessException(ResponseCode.FEIGN_SERVICE_ERROR);
        }else if(purchaseProcess.getCode()!=ResponseCode.SUCCESS.getCode()){
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_PROCESS_IS_NOT_ALLOW);
        }
    }

    /**
     * 查询物流单信息
     * @param logisticsId: 请求参数
     * @return 物流单信息
     */
    @Override
    public Wrapper<LogisticsOrderFeignResponse> getLogisticsOrder(Long logisticsId) {
        Wrapper<LogisticsOrderFeignResponse> wrapper =  logisticsOrderControllerFeign.getLogisticsOrder(logisticsId);
        FeignLogUtils.printLog("查询物流单信息",wrapper,logisticsId);
        return wrapper;
    }

    /**
     * 批量查询物流单信息
     * @param logisticsIds: 请求参数
     * @return 物流单信息
     */
    @Override
    public Wrapper<List<LogisticsOrderFeignResponse>> listLogisticsOrder(List<Long> logisticsIds) {
        Wrapper<List<LogisticsOrderFeignResponse>> wrapper =  logisticsOrderControllerFeign.listLogisticsOrder(logisticsIds);
        FeignLogUtils.printLog("批量查询物流单信息",wrapper,logisticsIds);
        return wrapper;
    }

    @Override
    public Map<Long, LogisticsOrderFeignResponse> listLogisticsOrderMap(List<Long> logisticsIds) {
        Wrapper<List<LogisticsOrderFeignResponse>> listWrapper = logisticsOrderControllerFeign.listLogisticsOrder(logisticsIds);
        FeignLogUtils.printLog("批量查询物流单信息 s2",listWrapper,logisticsIds);
        if(listWrapper!=null&& listWrapper.getCode()==ResponseCode.SUCCESS.getCode()){
            List<LogisticsOrderFeignResponse> logisticsOrderData = listWrapper.getData();
            if(CollectionUtil.isNotEmpty(logisticsOrderData)) {
                return logisticsOrderData.stream().collect(Collectors.toMap(LogisticsOrderFeignResponse::getId, o->o,(o1, o2)->o1));
            }
        }
        return null;
    }

    public Wrapper<OrderSettleAccountInvoiceFeignDetailVO> findSettleAccountInvoiceDetail(String orderNo){
        OrderNoFeignVO vo=new OrderNoFeignVO();
        vo.setOrderNo(orderNo);
        Wrapper<OrderSettleAccountInvoiceFeignDetailVO> wrapper = orderFeignService.findSettleAccountInvoiceDetail(vo);
        FeignLogUtils.printLog("查询订单是否需要开票",wrapper,orderNo);
        return wrapper;
    }

    public Wrapper<?> updateActivitySkuSales(GoodsSalesReq req){
        Wrapper<?> wrapper =  activityGoodsControllerFeign.updateGoodsSales(req);
        FeignLogUtils.printLog("更新活动商品销量信息",wrapper,req);
        return wrapper;
    }

    public Wrapper<Object> refundByAliPay(Long memberId,Long roleId,String transactionPayId,String orderNo,String refundNo,Integer payRuleId,Double refundAmount){
        AliPayRefundRequest request = new AliPayRefundRequest();
        request.setMemberId(memberId);
        request.setMemberRoleId(roleId);
        request.setTransactionId(transactionPayId);
        request.setOutTradeNo(orderNo);
        request.setOutRefundNo(refundNo);
        request.setPayType(payRuleId);
        request.setRefundMoney(refundAmount);
        Wrapper<Object> aliPayWrapper = aliPayFeign.refund(request);
        FeignLogUtils.printLog("支付宝退款",aliPayWrapper,request);
        return aliPayWrapper;
    }

    public Wrapper<Object> refundByWeChatPay(Long memberId,Long roleId,String transactionPayId,String orderNo,String refundNo,Double payAmount,Integer payRuleId,Double refundAmount){
        WeChatRefundRequest request = new WeChatRefundRequest();
        request.setMemberId(memberId);
        request.setMemberRoleId(roleId);
//        request.setTransactionId(transactionPayId);
//        request.setOutTradeNo(orderNo);
        request.setTransactionId("");
        request.setOutTradeNo(transactionPayId);
        request.setOutRefundNo(refundNo);
        request.setPayMoney(payAmount);
        request.setPayType(payRuleId);
        request.setRefundMoney(refundAmount);
        Wrapper<Object> weChatPayWrapper = weChatPayFeign.refund(request);
        FeignLogUtils.printLog("微信退款",weChatPayWrapper,request);
        return weChatPayWrapper;
    }

    @Override
    public Wrapper<?> addContractExecuteInfoList(List<ContractExecuteInfoAddVO> contractExecuteList) {
        Wrapper<Void> voidWrapper = contractExecuteControllerFeign.addList(contractExecuteList);
        FeignLogUtils.printLog("批量添加合同执行信息",voidWrapper,contractExecuteList);
        return voidWrapper;
    }

    @Override
    public Wrapper<RefundRespVO> refundByDirectAccount(EAccountRefundRequest request) {
        Wrapper<RefundRespVO> wrapper = allInPayFeign.orderRefund(request);
        FeignLogUtils.printLog("通联退款申请(1-会员直接到账; 2-平台代收并且平台还没结算给商家)",wrapper,request);
        return wrapper;
    }

    @Override
    public Wrapper<OrderSplitRefundRespVO> refundByPlatformExchange(StoreRefundRequest request) {
        Wrapper<OrderSplitRefundRespVO> wrapper = allInPayFeign.orderStoreRefund(request);
        FeignLogUtils.printLog("通联退款申请(平台代收并且平台已经结算给商家)",wrapper,request);
        return wrapper;
    }

    @Override
    public Wrapper<Boolean> checkAfterSaleOrderMember(CheckOrderMemberAfterSaleVO request) {
        Wrapper<Boolean> wrapper = orderFeignService.checkAfterSaleOrderMember(request);
        FeignLogUtils.printLog("售后服务 - 订单会员信息校验",wrapper,request);
        return wrapper;
    }

    @Override
    public Wrapper<List<OrderProductCouponFeignVO>> findOrderProductCouponAmounts(OrderFeignIdsVO request) {
        Wrapper<List<OrderProductCouponFeignVO>> wrapper = orderFeignService.findOrderProductCouponAmounts(request);
        FeignLogUtils.printLog("售后服务 - 订单使用平台优惠券信息查询",wrapper,request);
        return wrapper;
    }

    @Override
    public Wrapper<PlatformSettlementAllInPayVO> getPlatformSettlementByDetailPaymentId(Long payId) {
        Wrapper<PlatformSettlementAllInPayVO> wrapper = platformSettlementControllerFeign.getPlatformSettlementByDetailPaymentId(payId);
        FeignLogUtils.printLog("结算服务 - 根据支付记录获取平台结算单的支付号",wrapper,payId);

        return wrapper;
    }

    @Override
    public Wrapper<Boolean> refundByCcbPay(B2bRefundVO vo) {
        Wrapper<Boolean> booleanWrapper = ccbPayFeign.b2bRefund(vo);
        FeignLogUtils.printLog("建行b2b退款",booleanWrapper,vo);
        return booleanWrapper;
    }

    @Override
    public Wrapper<Boolean> refundByCcbDigitalPay(DigitalRefundVO vo) {
        Wrapper<Boolean> booleanWrapper = ccbPayFeign.digitalRefund(vo);
        FeignLogUtils.printLog("建行数字货币退款",booleanWrapper,vo);
        return booleanWrapper;
    }

    @Override
    public Wrapper<Boolean> balanceRefund(BalanceRefundRequest refundRequest) {
        Wrapper<Boolean> wrapper = assetAccountFeign.balanceRefund(refundRequest);
        FeignLogUtils.printLog("余额退款",wrapper,refundRequest);
        return wrapper;
    }

    /**
     * srm退货信息通知给结算服务
     *
     * @param orderVO 订单发货信息DTO
     */
    @Override
    public void notifySrmReturnSettlement(SettlementOrderVO orderVO) {
        orderVO.setBillType(ApplyAmountRowBillTypeEnum.RETURN_REQUEST.getCode());
        try {
            //转换为Json字符串，推送至消息队列
            String json = JSONUtil.toJsonStr(orderVO);
            logger.info("srm退货-通知结算mq信息 => " + json);
            rabbitTemplate.convertAndSend(SettleAccountsConstant.SA_AUTO_RECONCILIATION_EXCHANGE, SettleAccountsConstant.SA_AUTO_RECONCILIATION_ROUTINGKEY, json);
        } catch (Exception e) {
            logger.error("srm退货-通知结算mq信息异常, msg:",e);
        }
    }

    @Override
    public void sendMsgToSettleAccountMQ(Integer type, String message){
        SettleAccountQueueDTO queueDTO=new SettleAccountQueueDTO();
        queueDTO.setType(type);
        queueDTO.setMessage(message);
        logger.info("发送退货退平台优惠券消息到结算MQ, queueDTO:{},message:{}", JSONUtil.toJsonStr(queueDTO),message);
        rabbitTemplate.convertAndSend(SettleAccountsConstant.SETTLE_ACCOUNT_BASE_EXCHANGE,SettleAccountsConstant.SETTLE_ACCOUNT_BASE_ROUTING_KEY,JSONUtil.toJsonStr(queueDTO));
    }
}
